/**
 * 
 */
package com.gragra.cooccClustering;
import com.gragra.clustering.ClusteringAlgorithm;
import com.gragra.clustering.SimpleSamplingBasedClusterer;
import com.gragra.contextClusterer.EvaluateLeftRightClustering;
import com.gragra.parseOptions.ListOfDoubleOption;
import com.gragra.parseOptions.ListOfIntegerOption;
import com.gragra.parseOptions.Parser;
import com.gragra.sampling.annealingSchedules.LinearAnnealingFromMaxToMin;
import com.gragra.sampling.vector.LimitedClassesUnitCRPFactory;
/**
 * @author Christoph Teichmann
 * 02.06.2013
 */
public class CRPClustering extends EvaluateLeftRightClustering
{
	/**
	 * 
	 */
	private int	numberOfLabels = 20;
	/**
	 * 
	 */
	private final static String numLabOptions = "numLab";
	/**
	 * 
	 */
	private double concentrationParameter = 1.0;
	/**
	 * 
	 */
	private final static String concOption = "conc";
	/**
	 * 
	 */
	private double labelConcentrationParameter = 0.1;
	/**
	 * 
	 */
	private final static String lConcOption = "lconc";
	/**
	 * 
	 */
	private double stepSize = 1.0;
	/**
	 * 
	 */
	private final static String stepSizeOption = "annealRed";
	/**
	 * 
	 */
	private int	samplingIntervalSize = 1;
	/**
	 * 
	 */
	private final static String samplingIntervalOpt = "samplingInt";
	/**
	 * 
	 */
	private  int minSampling = 10;
	/**
	 * @return the numberOfLabels
	 */
	protected int getNumberOfLabels()
	{
		return this.numberOfLabels;
	}
	/**
	 * @return the concentrationParameter
	 */
	protected double getConcentrationParameter()
	{
		return this.concentrationParameter;
	}
	/**
	 * @return the labelConcentrationParameter
	 */
	protected double getLabelConcentrationParameter()
	{
		return this.labelConcentrationParameter;
	}
	/**
	 * @return the stepSize
	 */
	protected double getStepSize()
	{
		return this.stepSize;
	}
	/**
	 * @return the samplingIntervalSize
	 */
	protected int getSamplingIntervalSize()
	{
		return this.samplingIntervalSize;
	}
	/**
	 * @return the minSampling
	 */
	protected int getMinSampling()
	{
		return this.minSampling;
	}
	/**
	 * @return the maxAnneal
	 */
	protected double getMaxAnneal()
	{
		return this.maxAnneal;
	}
	/**
	 * @return the minAnneal
	 */
	protected double getMinAnneal()
	{
		return this.minAnneal;
	}
	/**
	 * 
	 */
	private final static String minSamplingOpt = "samp";
	/**
	 * 
	 */
	private int	burnIn = 10;
	/**
	 * 
	 */
	private final static String burnInOpt = "burnIn";
	/**
	 * 
	 */
	private double	maxAnneal = 10.0;
	/**
	 * 
	 */
	private final static String maxAnnealOption = "annStart";
	/**
	 * 
	 */
	private double	minAnneal = 0.1;
	/**
	 * 
	 */
	private final static String minAnnealOption = "annFinal";
	/* (non-Javadoc)
	 * @see com.gragra.contextClusterer.EvaluateContextClustering#makeClustering()
	 */
	@Override
	protected ClusteringAlgorithm makeClustering()
	{
		LimitedClassesUnitCRPFactory lcrp = new LimitedClassesUnitCRPFactory(numberOfLabels,this.labelConcentrationParameter, concentrationParameter,this.getThreads());
		SimpleSamplingBasedClusterer ssbc = new SimpleSamplingBasedClusterer(samplingIntervalSize, lcrp, minSampling, getBurnIn(), new LinearAnnealingFromMaxToMin(maxAnneal, minAnneal, stepSize),this.getThreads());
		return ssbc;
	}
	/* (non-Javadoc)
	 * @see com.gragra.contextClusterer.EvaluateContextClustering#setOptions(com.gragra.parseOptions.Parser)
	 */
	@Override
	protected void setOptions(Parser pr)
	{
		ListOfIntegerOption oi = (ListOfIntegerOption) pr.getInformation(burnInOpt);
		if(oi.hasBeenSet())
		{this.setBurnIn(oi.getSettings()[0]);}
		ListOfDoubleOption lod = (ListOfDoubleOption) pr.getInformation(concOption);
		if(lod.hasBeenSet())
		{this.concentrationParameter = lod.getSettings()[0];}
		lod = (ListOfDoubleOption) pr.getInformation(maxAnnealOption);
		if(lod.hasBeenSet())
		{this.maxAnneal = lod.getSettings()[0];}
		lod = (ListOfDoubleOption) pr.getInformation(minAnnealOption);
		if(lod.hasBeenSet())
		{this.minAnneal = lod.getSettings()[0];}
		oi = (ListOfIntegerOption) pr.getInformation(minSamplingOpt);
		if(oi.hasBeenSet())
		{this.minSampling = oi.getSettings()[0];}
		oi = (ListOfIntegerOption) pr.getInformation(numLabOptions);
		if(oi.hasBeenSet())
		{this.numberOfLabels = oi.getSettings()[0];}
		oi = (ListOfIntegerOption) pr.getInformation(samplingIntervalOpt);
		if(oi.hasBeenSet())
		{this.samplingIntervalSize = oi.getSettings()[0];}
		lod = (ListOfDoubleOption) pr.getInformation(stepSizeOption);
		if(lod.hasBeenSet())
		{this.stepSize = lod.getSettings()[0];}
		lod = (ListOfDoubleOption) pr.getInformation(lConcOption);
		if(lod.hasBeenSet())
		{this.labelConcentrationParameter = lod.getSettings()[0];}
		super.setOptions(pr);
	}
	/* (non-Javadoc)
	 * @see com.gragra.contextClusterer.EvaluateContextClustering#addOptions(com.gragra.parseOptions.Parser)
	 */
	@Override
	public void addOptions(Parser to)
	{
		to.addOption(burnInOpt, new ListOfIntegerOption("can be used to set the number of burn in steps"));
		to.addOption(concOption, new ListOfDoubleOption("can be used to set the concentration parameter for everything except the labels"));
		to.addOption(maxAnnealOption, new ListOfDoubleOption("can be used to set the starting annealing value"));
		to.addOption(minAnnealOption, new ListOfDoubleOption("can be used to set the minimum annealing value"));
		to.addOption(minSamplingOpt, new ListOfIntegerOption("sets the number of sampling steps that will be executed"));
		to.addOption(numLabOptions, new ListOfIntegerOption("sets the number of clusters that will be used"));
		to.addOption(samplingIntervalOpt, new ListOfIntegerOption("sets the number of iterations before a new sample is drawn"));
		to.addOption(stepSizeOption, new ListOfDoubleOption("sets the amout that will be subtracted from the annealing factor after each iteration"));
		to.addOption(lConcOption, new ListOfDoubleOption("can be used to set the label concentration parameter"));
		super.addOptions(to);
	}
	public int getBurnIn()
	{
		return burnIn;
	}
	public void setBurnIn(int burnIn)
	{
		this.burnIn = burnIn;
	}
}